最近在研究Dapper Source Code想要抽離一些部分封裝自己想要的SQLHelper
做一些簡單筆記整理分享給版友,假如有不足的地方也期待版友留言、討論
使用建議
原因效能快,QueryFirstOrDefault跟Query的效率比較參考,兩者在測試比較是87.80 us比94.05 us。
connection.Query("select * from T").FirstOrDefault();
connection.Query("select top 1 * from T");
改為
connection.QueryFirstOrDefault("select top 1 * from T");
至於要如何手寫一個Dapper QueryFirstOrDefault核心Core
我寫一個簡化版本(不實現Mapping)給讀者參考:
有幾個重點
CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow行為,這意思是告訴資料庫請按順序給我第一列資料就好,這是提高效率關鍵單次read讀取第一行資料資料,並使用空動作while把資料流快速讀完 (可以參考底下詳細說明)using System.Data;
using System.Data.Common;
public static class DapperDemo
{
	public static T QueryFirstOrDefault<T>(this IDbConnection connection,string sql,Func<IDataRecord,T> selector)
	{
		using (var cmd = connection.CreateCommand())
		{
			cmd.CommandText = sql;
			using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
			{
				var data = (reader.Read() && reader.FieldCount != 0) ? selector(reader) : default(T);
				while (reader.Read()) { }
				while (reader.NextResult()) { }
				return data;
			}
		}
	}
}
最後做測試Demo
void Main()
{
	using(var conn = Connection){
		conn.Open();
	
		//Test Data
		var cmd = conn.CreateCommand();
		cmd.CommandText = "with cte as ( select '0001' id,'ITWeiHan' name union all select '0002' id,'Henry' name ) select * into #T from cte ;";
		cmd.ExecuteNonQuery();
		//Query
		var result = conn.QueryFirstOrDefault("select top 1 * from #T", reader => new {id=reader.GetString(0),name=reader.GetString(1)});	
	}
}
資料流沒有讀完就 return,會發生什麼事情?
可以參考Dapper作者回應的ISSUE: Issue #1210 · StackExchange/Dapper
主要避免忽略錯誤,像是在DataReader提早關閉情況,並且前面已經跟系統強調行為是單列資料(CommandBehavior.SingleRow,CommandBehavior.SingleResult),所以不會增加多少成本。

跟S.O的DataReader底層介紹 c# - How DataReader works? - Stack Overflow
弱弱的問一下,資料流沒有讀完就 return,會發生什麼事情?
這是一個好問題
我這邊反編譯來查看Read方法但底層的call看不到
真的好神奇,期待答案。
米歐 底下更新Dapper作者的回應
暐翰
作者回真快
看很多套件作者不是不回
就是他自己也解決不了
真的 用心秒回作者 :D
原來是避免忽略錯誤的部分!又學到一點實務上不太會需要的知識XD
米歐
我覺得倒是不會
現在很多開發者都只會學怎麼用
很多概念根本不了解
導致大家寫出來的都差不多
而沒辦法寫出自己的東西
Homura
哈哈,可能彼此了解不多,這句話讓你誤會了。
我喜歡去鑽這種問題,也才會在這邊留言。
我覺得這內容很有幫助,但實務上真的很難碰到XD

主要避免忽略錯誤,像是在DataReader提早關閉錯誤情況
好奇,這在什麼情況下會發生? 
好問題 我想想怎麼模擬